package control;

import interfaces.CommandLine;

import storage.ManageData;
import utils.CommandAnalyzer;
import utils.DataFormat;
import basic.Date;
import domain.Budget;
import enums.Frequency;

//@author A0098891H
public class BudgetManager implements CommandLine{
	
	private double _totalBalance;
	private double _initialBalance;

	private Budget _dailyBudget;
	private Budget _weeklyBudget;
	private Budget _monthlyBudget;
	private Budget _yearlyBudget;
	private ExpenseManager _xpnMan;
	private IncomeManager _incomeMan;
	private LoanManager _loanMan;


	public BudgetManager(ExpenseManager xpnMan, IncomeManager incomeMan, LoanManager loanMan)
	{
		_xpnMan = xpnMan;
		_incomeMan = incomeMan;
		_loanMan = loanMan;
		
		this.initialize();
		updateBudget();


	}
	
	
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void updateBudget()
	{
		_totalBalance = _initialBalance 
				- _xpnMan.getTotalAmountOfAll() 
				+ _incomeMan.getTotalAmountOfAll()
				- _loanMan.getAmountOut();
		_dailyBudget.updateBudget(_xpnMan);
		_weeklyBudget.updateBudget(_xpnMan);
		_monthlyBudget.updateBudget(_xpnMan);
		_yearlyBudget.updateBudget(_xpnMan);
		
		
	}
	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean initialize()
	{
		if(loadAll()==false)
		{
			_initialBalance = 0;
			_totalBalance = 0;
			_dailyBudget = new Budget(Frequency.DAILY);
			_weeklyBudget = new Budget(Frequency.WEEKLY);
			_monthlyBudget = new Budget(Frequency.MONTHLY);
			_yearlyBudget = new Budget(Frequency.YEARLY);		
			_dailyBudget.turnOff();
			_weeklyBudget.turnOff();
			_monthlyBudget.turnOff();
			_yearlyBudget.turnOff();
		}
		return true;
	}
	
	/**
	 * 
	 * @param budgetManager
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(BudgetManager budgetManager)
	{
		this._initialBalance = budgetManager._initialBalance;
		this._totalBalance = budgetManager._totalBalance;
		this._dailyBudget = budgetManager._dailyBudget;
		this._weeklyBudget = budgetManager._weeklyBudget;
		this._monthlyBudget = budgetManager._monthlyBudget;
		this._yearlyBudget = budgetManager._yearlyBudget;
	}
	
	/**
	 * 
	 * @param type
	 * @param amount
	 * @param date
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean setBudget(Frequency type, double amount, Date date)
	{
		
		switch(type)
		{
		case DAILY:
			_dailyBudget.set(amount,date);
			return true;
		case WEEKLY:
			_weeklyBudget.set(amount,date);
			return true;
		case MONTHLY:
			_monthlyBudget.set(amount,date);
			return true;
		case YEARLY:
			_yearlyBudget.set(amount,date);
			return true;
		default:
			break;
		}

		return false;
	}
	
	/**
	 * 
	 * @param type
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean turnOff(Frequency type)
	{
		switch(type)
		{
		case DAILY:
			_dailyBudget.turnOff();
			return true;
		case WEEKLY:
			_weeklyBudget.turnOff();
			return true;
		case MONTHLY:
			_monthlyBudget.turnOff();
			return true;
		case YEARLY:
			_yearlyBudget.turnOff();
			return true;
		default:
			break;
		}
		return false;
	}

	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_totalBalance() {
		return _totalBalance;
	}

	/**
	 * 
	 * @param totalBalance
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_totalBalance(double totalBalance) {
		this._totalBalance = totalBalance;
	}
	
	/**
	 * 
	 * @param amount
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean addTotalBalance(double amount)
	{
		this._totalBalance +=amount;
		return true;
	}
	/**
	 * 
	 * @param amount
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean subtractTotalBalance(double amount)
	{
		this._totalBalance -= amount;
		return true;
	}
	/**
	 *
	 * @see interfaces.CommandLine#readCmd(java.lang.String)
	 * @param cmd
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public int readCmd(String cmd) {
		//<BUDGET>|<SET> <DAILY|WEEKLY|...> <AMOUNT> (COMPULSORY)
		//<DATE> (optional)
		//<BUDGET>|<REMOVE> <DAILY|WEEKLY...> 
		
		String str[] = cmd.split(",");
		for(int i=0;i<str.length;i++)
		{
			str[i] = str[i].trim();
		}
		int length = str.length;
		if(length < 2)
			return -1;

		switch(str[1].toLowerCase())
		{
		case "on":
			switch(str[2].toLowerCase())
			{
			case "daily":
				_dailyBudget.turnOn();
				break;
			case "weekly":
				_weeklyBudget.turnOn();
				break;
			case "monthly":
				_monthlyBudget.turnOn();
				break;
			case "yearly":
				_yearlyBudget.turnOn();
				break;
			}
			
			cmd = "budget,turnOff,"+str[2];
			
			break;
		case "Off":
			
			switch(str[2].toLowerCase())
			{
			case "daily":
				_dailyBudget.turnOff();
				break;
			case "weekly":
				_weeklyBudget.turnOff();
				break;
			case "monthly":
				_monthlyBudget.turnOff();
				break;
			case "yearly":
				_yearlyBudget.turnOff();
				break;
			default:
				return -1;
			}
			
			cmd = "budget,on,"+str[2];
			
			break;
		case "set":
			if(length < 4)
				return -1;
			Budget updatedBudget = null;
			Budget obsoleteBudget = null;
			switch(str[2].toLowerCase())
			{
			case "daily":
				updatedBudget = new Budget(Frequency.DAILY);
				obsoleteBudget = _dailyBudget;
				_dailyBudget = updatedBudget;
				break;
			case "weekly":
				updatedBudget = new Budget(Frequency.WEEKLY);
				obsoleteBudget = _weeklyBudget;
				_weeklyBudget = updatedBudget;
				break;
			case "monthly":
				updatedBudget = new Budget(Frequency.MONTHLY);
				obsoleteBudget = _monthlyBudget;
				_monthlyBudget = updatedBudget;
				break;
			case "yearly":
				updatedBudget = new Budget(Frequency.YEARLY);
				obsoleteBudget = _yearlyBudget;
				_yearlyBudget = updatedBudget;
				break;
			default:
				return -1;
			}
			updatedBudget.set(Double.parseDouble(str[3]));
			updatedBudget.set_startDate(CommandAnalyzer.getDate(str));
			
			cmd = "budget,set,"+ obsoleteBudget.writeToString();
			
			break;
		default:
			return -1;
		}
		
		return 0;
	}


	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean saveAll() {
		return ManageData.saveBudgetManagerToFile(this);
	}


	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean loadAll() {
		BudgetManager budgetManager = ManageData.loadBudgetFromFile();
		if(budgetManager==null)
			return false;
		this.set(budgetManager);
		
		return true;
	}
	
	/**
	 *
	 * @see java.lang.Object#toString()
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public String toString()
	{
		StringBuilder sb = new StringBuilder();
		sb.append("Total Balance: "+ _totalBalance +"\n");
		sb.append(_dailyBudget.toString());
		sb.append(_weeklyBudget.toString());
		sb.append(_monthlyBudget.toString());
		sb.append(_yearlyBudget.toString());
		return sb.toString();
	}
	
	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public Budget get_dailyBudget() {
		return _dailyBudget;
	}

	/**
	 * 
	 * @param _dailyBudget
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_dailyBudget(Budget _dailyBudget) {
		this._dailyBudget = _dailyBudget;
	}

	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public Budget get_weeklyBudget() {
		return _weeklyBudget;
	}

	/**
	 * 
	 * @param _weeklyBudget
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_weeklyBudget(Budget _weeklyBudget) {
		this._weeklyBudget = _weeklyBudget;
	}

	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public Budget get_monthlyBudget() {
		return _monthlyBudget;
	}

	/**
	 * 
	 * @param _monthlyBudget
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_monthlyBudget(Budget _monthlyBudget) {
		this._monthlyBudget = _monthlyBudget;
	}

	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public Budget get_yearlyBudget() {
		return _yearlyBudget;
	}

	/**
	 * 
	 * @param _yearlyBudget
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_yearlyBudget(Budget _yearlyBudget) {
		this._yearlyBudget = _yearlyBudget;
	}

	public double get_initialBalance() {
		return _initialBalance;
	}

	public void set_initialBalance(double initialBalance) {
		this._initialBalance = initialBalance;
	}
	public String printBudgetStatus()
	{
		StringBuilder sb = new StringBuilder();
		sb.append("Current Balance: ");
		sb.append(DataFormat.returnTwoDecimals(get_totalBalance()));
		sb.append("\n");
		sb.append(_dailyBudget.printStatus());
		sb.append(_weeklyBudget.printStatus());
		sb.append(_monthlyBudget.printStatus());
		sb.append(_yearlyBudget.printStatus());
		
		return sb.toString();
	}
}
